package me.youline.dataServer.service.socialAction.handler;

import java.util.Date;
import java.util.List;

import me.youline.dataServer.dao.SocialLatestNotificationRecordDAO;
import me.youline.dataServer.dao.UserBaseInfoDAO;
import me.youline.dataServer.dao.socialActionMsg.SocialActionMsgNotifyRecordDAO;
import me.youline.dataServer.entity.UserBaseInfo;
import me.youline.dataServer.entity.socialActionMsg.SocialActionBaseMsg;
import me.youline.dataServer.entity.socialActionMsg.SocialActionMsgNotifyRecord;
import me.youline.dataServer.service.LatestNotifyRecordService;
import me.youline.dataServer.service.socialAction.event.SocialActionCancelEvent;
import me.youline.dataServer.service.socialAction.event.SocialActionEvent;
import me.youline.dataServer.service.socialAction.event.SocialActionExeEvent;
import me.youline.dataServer.service.support.MobilePushService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

/**
 * 社交行为事件处理的抽象类，能够处理行为执行事件，与行为取消事件。 主要构成了动态数据持久化、手机端通知推送的模板业务，后续实现类可以基于抽象方法进行拓展。
 * 
 * @author linhan
 *
 */
public abstract class AbstractSocialActionEventHandler implements
		SocialActionEventHandler {

	@Autowired
	private SocialLatestNotificationRecordDAO latestDAO;

	@Autowired
	private SocialActionMsgNotifyRecordDAO notifyRecordDAO;

	@Autowired
	private UserBaseInfoDAO userBaseInfoDAO;

	@Autowired
	private LatestNotifyRecordService latestNotifyRecordService;

	@Autowired
	private MobilePushService mobileSvice;

	@Override
	@Transactional
	public void processSocialActionEvent(SocialActionEvent event) {
		if (event instanceof SocialActionCancelEvent) {
			this.handlerCancelEvent((SocialActionCancelEvent) event);
			return;
		} else {
			SocialActionBaseMsg msg = this
					.extractSocialActionMsg((SocialActionExeEvent) event);
			List<Long> notifiedUserIds = this
					.decideNotifiedUsers((SocialActionExeEvent) event);
			this.doMsgAndEventProcess(msg, (SocialActionExeEvent) event);
			Long latestId = null;
			for (Long userId : notifiedUserIds) {
				SocialActionMsgNotifyRecord r = new SocialActionMsgNotifyRecord();
				r.setMsgId(msg.getId());
				r.setMsgType(msg.getMsgType());
				r.setNotifyTime(new Date());
				r.setUserId(userId);
				latestId = notifyRecordDAO.addSocialActionMsgNotifyRecord(r);
				latestNotifyRecordService.setAsLatestRecord(userId, latestId);
			}

		}

	}
	
	@Override
	public boolean isNeedHandle(SocialActionEvent event) {
		if (event instanceof SocialActionExeEvent) {
			List<Long> list = this.decideNotifiedUsers((SocialActionExeEvent) event);
			if(list.contains(event.getInitiator())){
				return false;
			}
		}
		return true;
	}

	@Override
	public void finishSocialActionEvent(SocialActionEvent event) {
		if (event instanceof SocialActionCancelEvent) {
			return;
		} else {// 执行消息推送
			UserBaseInfo base = userBaseInfoDAO.findOne(event.getInitiator());
			for (Long userId : decideNotifiedUsers((SocialActionExeEvent) event)) {
				int unRead = latestNotifyRecordService.getUnReadTotal(userId);
				MobilePushHelper helper = new MobilePushHelper(base,
						getPushFormat(), unRead, userId);
				helper.doPublish(mobileSvice);
			}
		}
	}

	/**
	 * 获取推送通知的消息格式
	 * 
	 * @return
	 */
	abstract protected String getPushFormat();

	/**
	 * 从社交行为事件中获取社交行为通知消息
	 * 
	 * @param event
	 * @return
	 */
	protected SocialActionBaseMsg extractSocialActionMsg(
			SocialActionExeEvent event) {
		SocialActionBaseMsg msg = this.extractMsgExtensionProp(event);
		msg.setInitiatorId(event.getInitiator());
		msg.setCreateTime(new Date());
		msg.setTargetId(event.getTargetId());
		return msg;
	}

	/**
	 * 决定被通知列表
	 * 
	 * @param event
	 * @return
	 */
	abstract List<Long> decideNotifiedUsers(SocialActionExeEvent event);

	/**
	 * 从事件中为不同的事件通知消息的特殊字段获取数据
	 * 
	 * @param event
	 * @return
	 */
	abstract protected SocialActionBaseMsg extractMsgExtensionProp(
			SocialActionExeEvent event);

	/**
	 * 处理社交行为取消事件
	 * 
	 * @param event
	 */
	abstract protected void handlerCancelEvent(SocialActionCancelEvent event);

	/**
	 * 对行为事件及其行为事件通知消息执行处理。此类将会根据消息与事件执行相应的持久化操作，以及确定具体的通知人
	 * 
	 * @param msg
	 * @param event
	 */
	abstract protected void doMsgAndEventProcess(SocialActionBaseMsg msg,
			SocialActionExeEvent event);

}
